import uuid
import logging
import time
from datetime import datetime, timedelta
from typing import Tuple, List
from pymongo import errors
from be.model import db_conn, error, user
from fe.data.utils import cut_word


class Buyer(db_conn.DBConn):
    """
    买家功能操作类
    - 负责处理用户下单、支付、订单查询等核心业务流程
    - 使用 MongoDB 作为数据存储后端
    """

    def __init__(self):
        """初始化买家实例，连接 MongoDB 集合"""
        super().__init__()
        self.User = user.User()  # 用户操作工具类
        self.store = self.conn['store']  # 店铺集合
        self.user = self.conn['user']    # 用户集合
        self.book = self.conn['book']    # 书籍库存集合
        self.order = self.conn['order']  # 订单集合

    def new_order(self, user_id: str, store_id: str, id_and_count: List[Tuple[str, int]], token: str) -> Tuple[int, str, str]:
        """
        创建新订单
        :param user_id: 买家用户ID
        :param store_id: 店铺ID
        :param id_and_count: 书籍ID与购买数量列表，格式 [(book_id, count), ...]
        :param token: 用户认证令牌
        :return: (状态码, 消息, 订单ID)
        """
        order_id = ""
        try:
            # 验证用户和店铺存在性
            if not self.user_id_exist(user_id):
                return error.error_non_exist_user_id(user_id) + (order_id,)
            if not self.store_id_exist(store_id):
                return error.error_non_exist_store_id(store_id) + (order_id,)
            
            # 生成唯一订单ID: 用户ID_店铺ID_UUID
            uid = f"{user_id}_{store_id}_{uuid.uuid1()}"
            
            order_amount = 0
            book_id_list = []
            book_count_list = []
            
            # 遍历每个商品进行库存检查
            for book_id, count in id_and_count:
                # 查询书籍库存信息
                book_data = self.book.find_one({'belong_store_id': store_id, 'book_id': book_id})
                if book_data is None:
                    return error.error_non_exist_book_id(book_id) + (order_id,)
                
                stock_level = book_data['stock_level']
                price = book_data.get("price")
                
                # 库存不足检查
                if stock_level < count:
                    return error.error_stock_level_low(book_id) + (order_id,)
                
                # 原子操作减少库存
                self.book.update_one(
                    {'belong_store_id': store_id, 'book_id': book_id, 'stock_level': {'$gte': count}},
                    {'$inc': {'stock_level': -count}}
                )
                
                # 记录订单详情
                book_id_list.append(book_id)
                book_count_list.append(count)
                order_amount += (price * count)
            
            # 构建订单文档
            create_time = datetime.now()
            payment_deadline = create_time + timedelta(minutes=30)  # 30分钟支付时限
            new_order_data = {
                'order_id': uid,
                'buyer_id': user_id,
                'create_time': create_time.strftime("%Y-%m-%d %H:%M:%S"),
                'payment_deadline': payment_deadline.strftime("%Y-%m-%d %H:%M:%S"),
                'state': 0,  # 订单状态: 0-未支付
                'order_amount': order_amount,
                'seller_store_id': store_id,
                'purchased_book_id': book_id_list,
                'purchase_quantity': book_count_list
            }
            
            # 插入订单数据
            self.order.insert_one(new_order_data)
            order_id = uid
            
        except errors.PyMongoError as e:
            logging.error(f"数据库操作异常: {e}")
            return 528, f"{str(e)}", ""
        except BaseException as e:
            logging.error(f"系统异常: {e}")
            return 530, f"{str(e)}", ""

        return 200, "ok", order_id

    def payment(self, user_id: str, password: str, order_id: str) -> Tuple[int, str]:
        """
        执行订单支付
        :param user_id: 支付用户ID
        :param password: 用户密码
        :param order_id: 待支付订单ID
        :return: (状态码, 消息)
        """
        try:
            # 查询订单信息
            order_data = self.order.find_one({'order_id': order_id})
            if order_data is None:
                return error.error_invalid_order_id(order_id)
            
            buyer_id = order_data['buyer_id']
            total_price = order_data['order_amount']
            
            # 验证支付人身份
            if buyer_id != user_id:
                return error.error_authorization_fail()
            
            # 获取用户余额信息
            user_data = self.user.find_one({'user_id': buyer_id}, {'balance': 1, "password": 1})
            if user_data['password'] != password:
                return error.error_authorization_fail()
            
            # 余额检查
            balance = user_data['balance']
            if balance < total_price:
                return error.error_account_balance(buyer_id)
            
            # 扣减余额（原子操作）
            self.user.update_one(
                {'user_id': buyer_id, 'balance': {'$gte': total_price}},
                {'$inc': {'balance': -total_price}}
            )
            
            # 更新订单状态为已支付
            self.order.update_one(
                {'order_id': order_id},
                {'$set': {'state': 1}}  # 1-已支付
            )
            
        except errors.PyMongoError as e:
            return error.database_error(e)
        except BaseException as e:
            return 530, f"{str(e)}"

        return 200, "Payment successful"

    def add_funds(self, user_id: str, password: str, add_value: int) -> Tuple[int, str]:
        """
        用户账户充值
        :param user_id: 用户ID
        :param password: 用户密码
        :param add_value: 充值金额
        :return: (状态码, 消息)
        """
        try:
            # 验证用户身份
            user_data = self.user.find_one({'user_id': user_id})
            if user_data is None or user_data['password'] != password:
                return error.error_authorization_fail()
            
            # 执行充值操作
            self.user.update_one(
                {'user_id': user_id},
                {'$inc': {'balance': add_value}}
            )
            
        except errors.PyMongoError as e:
            return error.database_error(e)
        except BaseException as e:
            return 530, f"{str(e)}"
            
        return 200, "ok"

    def receive(self, user_id: str, order_id: str, token: str) -> Tuple[int, str]:
        """
        确认收货操作
        :param user_id: 用户ID
        :param order_id: 订单ID
        :param token: 用户令牌
        :return: (状态码, 消息)
        """
        try:
            # 令牌有效性验证
            code, message = self.User.check_token(user_id, token)
            if code != 200:
                return code, message
            
            # 查询订单并验证状态
            order_data = self.order.find_one({"order_id": order_id})
            if order_data is None:
                return error.error_non_exist_order_id(order_id)
            if order_data['state'] != 2:  # 2-已发货状态才能确认收货
                return error.error_order_state(order_data['state'])
            
            # 更新订单状态为已收货
            self.order.update_one(
                {"order_id": order_id, "buyer_id": user_id},
                {"$set": {"state": 3}}  # 3-已收货
            )
            
        except errors.PyMongoError as e:
            return error.database_error(e)
        except BaseException as e:
            return 530, f"{str(e)}"

        return 200, "ok"

    def search_global(self, keyword: str, page: int) -> Tuple[int, str, list]:
        """
        全局商品搜索
        :param keyword: 搜索关键词
        :param page: 分页页码（0表示全部）
        :return: (状态码, 消息, 结果列表)
        """
        try:
            # 中文分词处理
            keywords = ' '.join(cut_word(keyword))
            
            # 执行全文检索查询
            query = self.book.find(
                {'$text': {'$search': keywords}},
                {'_id': 0, '_t': 0}  # 排除 MongoDB 系统字段
            )
            
            # 分页处理
            if page > 0:
                results = list(query.skip((page-1)*self.page_size).limit(self.page_size))
            elif page == 0:
                results = list(query)
            else:
                return error.error_invalid_parameter(page) + ([],)
                
        except Exception as e:
            return 401, f"{str(e)}", []
            
        return 200, 'ok', results
    
    def search_in_store(self, keyword, page, store_id) -> (int, str, list):
        try:
            if not self.store_id_exist(store_id):
                return error.error_non_exist_store_id(store_id) + ([],)
            keywords = ' '.join(cut_word(keyword))
            results = self.book.find({'$text':{'$search': keywords}, 'belong_store_id':store_id}, {'_id':0, '_t':0})
            if page > 0:
                results = list(results.skip((page-1)*self.page_size).limit(self.page_size))
            elif page == 0:
                results = list(results)
            else:
                return error.error_invalid_parameter(page) + ([],)
            results = list(results)
            return 200,'ok', results
        except Exception as e:
            return 401, "{}".format(str(e)), ([],)

    def search_order(self, user_id: str, search_state: int) -> (int, str, list):
        try:
            if not self.user_id_exist(user_id):
                return error.error_non_exist_user_id(user_id) + ([],)
            results = [] # 定义返回结果，为list
            # 查询所有订单
            if search_state == 0:
                results = self.order.find({'buyer_id': user_id})
                results = list(results)
            # 查询待支付订单
            elif search_state == 1:
                results = self.order.find({'buyer_id': user_id, 'state': 0})
                results = list(results)
            # 查询已支付未发货
            elif search_state == 2:
                results = self.order.find({'buyer_id': user_id, 'state': 1})
                results = list(results)
            # 查询已发货未收货
            elif search_state == 3:
                results = self.order.find({'buyer_id': user_id, 'state': 3})
                results = list(results)
            # 查询已收货
            elif search_state == 4:
                results = self.order.find({'buyer_id': user_id, 'state': 4})
                results = list(results)
            # 查询已取消订单
            elif search_state == 5:
                results = self.order.find({'buyer_id': user_id, 'state': 5})
                results = list(results)
        except BaseException as e:
            return 530, "{}".format(str(e)), []
        return 200, "ok", results

    def delete_order(self, user_id: str, order_id: str) -> (int, str):
        if not self.user_id_exist(user_id):
            return error.error_non_exist_user_id(user_id) + ([],)

        # 查询属于未付款的订单（并且满足order_id）
        order_col = self.conn['order']
        result = order_col.find_one({'buyer_id': user_id,
                                     'order_id': order_id,
                                     'state': {'$in': [0, 1]}})

        if result is not None:
            # 属于未付款订单，不需要更新用户余额，但是需要更新店铺剩余数量
            if result.get("state") == 0:
                self.order.update_one({'buyer_id': user_id,
                                       'order_id': order_id,
                                       'state': 0},
                                      {'$set': {'state': 5}})  # 修改待付款订单或未发货订单状态为删除状态
            # 否则的话，就属于已付款未发货订单，那么需要更改用户余额
            elif result.get("state") == 1:
                self.user.update_one({'user_id': user_id},
                                     {'$inc': {'balance': result.get("order_amount")}})
            # 否则的话，就无法取消，需要申请售后
            else:
                return error.error_invalid_order_id(order_id)

        # purchased_book_id, purchase_quantity, 更新商店库存
        purchased_book_id = result.get('purchased_book_id')
        purchase_quantity = result.get('purchase_quantity')
        store_id = result.get('seller_store_id')

        for i in range(len(purchase_quantity)):
            _id = purchased_book_id[i]
            _q = purchase_quantity[i]
            self.book.update_one({'belong_store_id': _id, 'seller_store_id': store_id},
                                 {'$inc': {'stock_level': _q}})
        return 200, 'ok'

    def delete_order_time(self):
        try:
            order_col = self.conn['order']
            now = datetime.now()
            orders = order_col.find({"deadline":  {"$lt":  now}, "state": 0})
            for order in orders:
                order_col.delete_one({"order_id": order["order_id"]})
        except errors.PyMongoError as e:
            return 528, "{}".format(str(e))
        except BaseException as e:
            return 530, "{}".format(str(e))
        return 200, "ok"
